package com.piece.mall.service;

import com.piece.core.framework.constant.CookieConstants;
import com.piece.core.framework.enums.StatusType;
import com.piece.core.framework.support.convert.Convert;
import com.piece.core.framework.util.collection.CollectionUtil;
import com.piece.core.framework.util.string.JsonUtil;
import com.piece.core.framework.util.string.StringUtil;
import com.piece.core.log.config.UserContextHolder;
import com.piece.core.web.cookie.CookieUtil;
import com.piece.core.web.util.ServletUtil;
import com.piece.mall.api.constant.MallConstant;
import com.piece.mall.api.dto.CartDTO;
import com.piece.mall.api.dto.CartItemDTO;
import com.piece.mall.model.PmsSkuInfo;
import com.piece.mall.model.PmsSkuSaleAttrValue;
import com.piece.mall.repository.PmsSkuSaleAttrValueRepository;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

@Service
@Transactional
public class CartService {

    @Resource
    private ThreadPoolTaskExecutor taskExecutor;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private PmsSkuInfoService pmsSkuInfoService;

    @Resource
    private PmsSkuSaleAttrValueRepository pmsSkuSaleAttrValueRepository;

    /**
     * 添加商品到购物车
     */
    public CartItemDTO addToCart(Long skuId, Integer num) throws ExecutionException, InterruptedException {
        // 获取购物车信息
        BoundHashOperations<String, Object, Object> operations = getUserCartOperations();
        // 获取商品
        String cartItemString = (String) operations.get(skuId.toString());
        if (StringUtil.isEmpty(cartItemString)) {
            CartItemDTO item = new CartItemDTO();
            CompletableFuture<Void> getSkuInfoFuture = CompletableFuture.runAsync(() -> {
                // 查询当前商品信息
                PmsSkuInfo skuInfo = pmsSkuInfoService.findById(skuId);
                item.setSkuId(skuInfo.getSkuId());
                item.setTitle(skuInfo.getSkuTitle());
                item.setImage(skuInfo.getSkuDefaultImg());
                item.setPrice(skuInfo.getPrice());
                item.setCount(num);
                item.setCheck(true);
            }, taskExecutor);

            CompletableFuture<Void> getSkuAttrValuesFuture = CompletableFuture.runAsync(() -> {
                // 查询销售属性信息
                List<PmsSkuSaleAttrValue> saleAttrs = pmsSkuSaleAttrValueRepository.findByCondition("skuId", skuId, null);
                List<String> skuSaleAttrValues = saleAttrs.stream().map(attr -> attr.getAttrName() + ":" + attr.getAttrValue())
                        .collect(Collectors.toList());
                item.setSkuAttrValues(skuSaleAttrValues);
            }, taskExecutor);

            CompletableFuture.allOf(getSkuInfoFuture, getSkuAttrValuesFuture).get();
            operations.put(skuId.toString(), JsonUtil.toJson(item));
            return item;
        } else {
            CartItemDTO item = JsonUtil.toBean(cartItemString, CartItemDTO.class);
            item.setCount(item.getCount() + num);
            operations.put(skuId.toString(), JsonUtil.toJson(item));
            return item;
        }
    }

    /**
     * 获取商品信息
     */
    public CartItemDTO getCartItem(Long skuId) {
        // 获取购物车信息
        BoundHashOperations<String, Object, Object> operations = getUserCartOperations();
        String cartItemString = (String) operations.get(skuId.toString());
        CartItemDTO item = JsonUtil.toBean(cartItemString, CartItemDTO.class);
        return item;
    }

    /**
     * 获取购物车列表
     */
    public CartDTO getCart() throws ExecutionException, InterruptedException {
        String userId = getCurrentUser();
        CartDTO cart = new CartDTO();
        // 获取当前购物车
        List<CartItemDTO> touristItems = getCartItems(MallConstant.CART_PREFIX + userId);
        if (null == UserContextHolder.get()) {
            // 游客状态,返回购物车
            cart.setItems(touristItems);
        } else {
            // 登录状态,清空游客购物车
            if (CollectionUtil.isNotEmpty(touristItems)) {
                // 整合游客购物车到用户购物车
                for (CartItemDTO item : touristItems) {
                    // 将商品放到用户购物车
                    addToCart(item.getSkuId(), item.getCount());
                }
                // 清空游客购物车
                clearCart(MallConstant.CART_PREFIX + CookieUtil.getCookieValue(ServletUtil.getRequest(), CookieConstants.SESSION_KEY));
            }

            // 获取用户购物车
            List<CartItemDTO> items = getCartItems(MallConstant.CART_PREFIX + userId);
            cart.setItems(items);
        }

        return cart;
    }

    /**
     * 改变商品选中状态
     */
    public void changeItemChecked(Long skuId, Integer check) {
        // 查询购物车商品信息
        CartItemDTO item = getCartItem(skuId);
        // 修改商品选中状态
        item.setCheck(StatusType.NORMAL.getCode().equals(Convert.toStr(check, "1")) ? true : false);
        // 更新到redis中
        BoundHashOperations<String, Object, Object> operations = getUserCartOperations();
        operations.put(skuId.toString(), JsonUtil.toJson(item));
    }

    /**
     * 改变商品数量
     */
    public void changeItemCount(Long skuId, Integer num) {
        // 查询购物车商品信息
        CartItemDTO item = getCartItem(skuId);
        // 修改商品数量
        item.setCount(num);
        // 更新到redis中
        BoundHashOperations<String, Object, Object> operations = getUserCartOperations();
        operations.put(skuId.toString(), JsonUtil.toJson(item));
    }

    /**
     * 删除购物项
     */
    public void deleteCartItem(Integer skuId) {
        BoundHashOperations<String, Object, Object> operations = getUserCartOperations();
        operations.delete(skuId.toString());
    }

    /**
     * 清空购物车
     */
    public void clearCart(String cartKey) {
        redisTemplate.delete(cartKey);
    }

    /**
     * 获取当前用户购物车
     */
    private BoundHashOperations getUserCartOperations() {
        String userId = getCurrentUser();
        String cartKey = MallConstant.CART_PREFIX + userId;
        return redisTemplate.boundHashOps(cartKey);
    }

    private List<CartItemDTO> getCartItems(String cartKey) {
        BoundHashOperations<String, Object, Object> operations = redisTemplate.boundHashOps(cartKey);
        List<Object> values = operations.values();
        if (CollectionUtil.isNotEmpty(values)) {
            // 封装商品集合
            return values.stream()
                    .map(jsonString -> JsonUtil.toBean((String) jsonString, CartItemDTO.class))
                    .collect(Collectors.toList());
        }
        return null;
    }

    private String getCurrentUser() {
        String userId = UserContextHolder.getUserId();
        if (StringUtil.isEmpty(userId)) {
            userId = CookieUtil.getCookieValue(ServletUtil.getRequest(), CookieConstants.SESSION_KEY);
        }
        return userId;
    }
}
